Facade Pattern

Facade Pattern က Structural-Pattern တစ်ခု ဖြစ်ပါတယ်။ သူက တံခါးပေါက်နဲ့ တူပါတယ်။​ System အကြီးရဲ့ အောက်မှာ sub system တွေ ရှိနေပြီး သူတို့ကို Service Class ကနေ တဆင့်ခိုင်းစေတာပါ။

သူ့ class diagram မှာ Facade နဲ့ Client ပါဝင်ပါတယ်။

Client က နေ တစ်ခုခု ကို Facade ကို ခိုင်းလိုက်ပါတယ်။ Facade က သက်ဆိုင်ရာ class တွေကို ခိုင်းပြီး အလုပ်လုပ်သွားသည့် သဘောပါ။

ဥပမာ နားလည်အောင် အောက်က Diagram ကို ကြည့်ကြည့်ပါ။

HomeTheaterFacade က main system ဖြစ်ပြီး သူ့ဆီမှာ sub system တွေ ဖြစ်သည့် DVD Player, Projector, Sound System တွေ ရှိနေပါတယ်။

ကျွန်တော်တို့ ဘယ် DVD Player သုံးမယ်။ ဘယ် Projector သုံးမယ်။​ ဘယ် Sound System သုံးမယ် ဆိုတာကို HomeTheaterFacade မှာ initalize လုပ်ပေးပြီး watchMovie ဆိုရင် sub system တွေ အကုန်လုံး အလုပ်လုပ်မှာပါ။ အဲဒီ အတိုင်း endMovie ဆိုရင် sub system တွေ အကုန် ရပ်သွားမှာပါ။

Java code နဲ့ တချက်ကြည့်ရအောင်။

DVDPlayer.java 

public class DVDPlayer {
    public void on() {
        System.out.println("DVD Player is ON");
    }

    public void play(String movie) {
        System.out.println("Playing " + movie);
    }

    public void stop() {
        System.out.println("DVD Player stopped");
    }

    public void off() {
        System.out.println("DVD Player is OFF");
    }
}

Projector.java

public class Projector {
    public void on() {
        System.out.println("Projector is ON");
    }

    public void setInput(DVDPlayer dvdPlayer) {
        System.out.println("Setting input to DVD Player");
    }

    public void display() {
        System.out.println("Projector is displaying");
    }

    public void off() {
        System.out.println("Projector is OFF");
    }
}

SoundSystem.java

public class SoundSystem {
    public void on() {
        System.out.println("Sound System is ON");
    }

    public void setVolume(int volume) {
        System.out.println("Setting volume to " + volume);
    }

    public void surroundSound() {
        System.out.println("Surround sound is ON");
    }

    public void off() {
        System.out.println("Sound System is OFF");
    }
}

HomeTheaterFacade.java

public class HomeTheaterFacade {
    private DVDPlayer dvdPlayer;
    private Projector projector;
    private SoundSystem soundSystem;

    public HomeTheaterFacade(DVDPlayer dvdPlayer, Projector projector, SoundSystem soundSystem) {
        this.dvdPlayer = dvdPlayer;
        this.projector = projector;
        this.soundSystem = soundSystem;
    }

    public void watchMovie(String movie) {
        System.out.println("Get ready to watch a movie...");
        dvdPlayer.on();
        dvdPlayer.play(movie);
        projector.on();
        projector.setInput(dvdPlayer);
        projector.display();
        soundSystem.on();
        soundSystem.setVolume(10);
        soundSystem.surroundSound();
    }

    public void endMovie() {
        System.out.println("Shutting down the movie theater...");
        dvdPlayer.stop();
        dvdPlayer.off();
        projector.off();
        soundSystem.off();
    }
}

အခု HomeTheaterFacade ကို ခေါ်သုံးပါမယ်။

public class Main {
    public static void main(String[] args) {
        // Create the subsystem components
        DVDPlayer dvdPlayer = new DVDPlayer();
        Projector projector = new Projector();
        SoundSystem soundSystem = new SoundSystem();

        // Create the facade
        HomeTheaterFacade homeTheaterFacade = new HomeTheaterFacade(dvdPlayer, projector, soundSystem);

        // Watch a movie using the Facade
        homeTheaterFacade.watchMovie("Avatar");

        // End the movie and shut down the system
        homeTheaterFacade.endMovie();
    }
}

နောက်ပြီး နေ့စဥ် သုံးနေကျ စနစ်တွေမှာဆိုရင်တော့ Facade က Service class နဲ့ တူပါတယ်။ သူကနေ တဆင့် database ကို CRUD တွေ အပြင် အခြား သက်ဆိုင်ရာ sub system တွေကို ခေါ်ပြီး အသုံးပြုပါတယ်။

User class ကို ကြည့်ရအောင်။

User.java

// User class representing the domain entity
class User {
    private String id;
    private String name;
    // Other user properties, getters, setters, etc.
}

UserRepository.java

// Data Access Layer
class UserRepository {
    public User saveUser(User user) {
        // Persist the user in the database and return the saved user
    }

    public User getUserById(String userId) {
        // Retrieve user from the database using the provided ID
    }

    public void deleteUser(String userId) {
        // Delete user from the database using the provided ID
    }
}

EmailService.java

// Integration Layer
class EmailService {
    public void sendWelcomeEmail(User user) {
        // Send a welcome email to the user
    }
}

UserManager.java

// Business Logic Layer
class UserManager {
    private UserRepository userRepository;
    private EmailService emailService;

    public UserManager(UserRepository userRepository, EmailService emailService) {
        this.userRepository = userRepository;
        this.emailService = emailService;
    }

    public User createUser(String name) {
        User newUser = new User();
        newUser.setName(name);

        // Save the user in the database
        User savedUser = userRepository.saveUser(newUser);

        // Send a welcome email to the user
        emailService.sendWelcomeEmail(savedUser);

        return savedUser;
    }

    public User getUserById(String userId) {
        return userRepository.getUserById(userId);
    }

    public void deleteUser(String userId) {
        userRepository.deleteUser(userId);
    }
}

UserManagementFacade.java

// Facade to provide a simplified interface to interact with different layers
class UserManagementFacade {
    private UserManager userManager;

    public UserManagementFacade() {
        UserRepository userRepository = new UserRepository();
        EmailService emailService = new EmailService();
        this.userManager = new UserManager(userRepository, emailService);
    }

    public User createUser(String name) {
        return userManager.createUser(name);
    }

    public User getUserById(String userId) {
        return userManager.getUserById(userId);
    }

    public void deleteUser(String userId) {
        userManager.deleteUser(userId);
    }
}

Main.java

// Presentation Layer (Main Application)
public class Main {
    public static void main(String[] args) {
        UserManagementFacade facade = new UserManagementFacade();

        // Create a new user
        User newUser = facade.createUser("John Doe");
        System.out.println("User created with ID: " + newUser.getId());

        // Get a user by ID
        String userId = newUser.getId();
        User retrievedUser = facade.getUserById(userId);
        System.out.println("User retrieved: " + retrievedUser.getName());

        // Delete the user
        facade.deleteUser(userId);
        System.out.println("User with ID " + userId + " deleted.");
    }
}

UserManagementFacade က ရိုးရှင်း ပုံစံ ရှိပြီးတော့ UserManager က အနည်းငယ် ရှုပ်ထွေးပါတယ်။ UserRepository, EmailService ကို အသုံးပြုသူက တည်ဆောက်ဖို့ မလိုပဲ UserManagementFacade က တည်ဆောက်ပေးပြီး User တွေကို create, get, delete လုပ်သည့် အခါမှာ ရိုးရှင်း လွယ်ကူစေပါတယ်။

Sequence Diagram ကို ကြည့်လိုက် သည့် အခါမှာ ပိုရှင်းလင်း ပြီး သဘောပေါက်ပါလိမ့်မယ်။

Application Layer

Software System တစ်ခု မှာ ရှိသည့် layer တွေ အရ Facade pattern ဟာ service layer မှာ ရှိပါတယ်။ Layer တွေကို ခွဲထုတ်ရေးရတာကလည်း Single Responsiblity ဖြစ်ချင်လို့ပါ။

  • Presentation Layer
  • Service Layer
  • Business Logic Layer
  • Integration Layer
  • Data Access Layer

Pros and Cons

ကောင်းချက်ကတော့ complex ဖြစ်သည့် subsystem က code တွေကို isolate လုပ်ထားနိုင်ပါတယ်။ Facades pattern ဟာ unit testing နဲ့ integration testing တွေ အတွက် အဆင်ပြေပါတယ်။

မကောင်းတာကတော့ facade က a god object ဖြစ်နေလို့ပါပဲ။ သူကနေ အကုန်လုံးကို ထိန်းချုပ်ထားသည့် သဘောမျိုးပါ။